#ifndef _YSORTEDLIST_H
#define _YSORTEDLIST_H
#include <tool/ydefine.h>

/** Function pointers struct, use externally */
typedef struct sortedList *sortedList;
/** Data struct, use internally */
typedef struct sortedListData *sortedListData;

/** Struct of sorted list function pointers */
struct sortedList {
  /*--- data ---*/
  sortedListData d;
  /*--- function pointers ---*/
  /** Free this sorted List from memory.
  @param listP pass in the address of sorted List struct pointer to be free.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*free)(sortedList *listP);
  /** Change <code>lesserFirst</code> value.
  <p>Default <code>lesserFirst</code> is set to <code>true</code>. 
  If set to <code>true</code> sorting will place 
  item whose comparison value is lesser at the front. 
  Otherwise set to <code>false</code> sorting will place 
  item whose comparison value is greater at the front. 
  </p>
  @param list the sorted list.
  @param lesserFirst to sort list by greater first set this to <code>false</code> 
    otherwise set to <code>true</code> to place lesser first.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*setLesserFirst)(sortedList list, 
      const boolean lesserFirst);
  /** Is list sort by lesser first?
  Query <code>lesserFirst</code> value.
  @param list the sorted list.
  @return <code>g_replyYes</code> if value is <code>true</code>, 
    <code>g_replyNo</code> if value is <code>false</code>,
    or <code>g_replyFail</code> if failure occurs.
  */
  g_reply (*isLesserFirst)(const sortedList list);
  /** Returns the number of elements in this list.
  @param list the sorted list.
  @return Returns the number of elements in this list or -1 if failure.
  */
  int (*size)(const sortedList list);
  /** Removes all of the elements from this list.
  @param list the sorted list.
  @return <code>true</code> if successful 
    otherwise <code>false</code> nothing to remove.
  */
  boolean (*clear)(sortedList list);
  /*--- traverse */
  /** If the list currently point at something.
  @param list the sorted list.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*current)(const sortedList list);
  /** Move to next item. Successful if next in list point at something, 
  otherwise stay at the tail of the list.
  @param list the sorted list.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*goNext)(sortedList list);
  /** Move back a item. Successful if previous in list point at something, 
  otherwise stay at the head of the list.
  @param list the sorted list.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*goBack)(sortedList list);
  /** Move to the first item in the list. 
  @param list the sorted list.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*goFirst)(sortedList list);
  /** Move to the last item in the list. 
  @param list the sorted list.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*goLast)(sortedList list);
  /*--- test */
  /** Tests if this list has no elements.
  @param list the sorted list.
  @return <code>true</code> if successful otherwise <code>false</code>.
  */
  boolean (*isEmpty)(const sortedList list);
  /** Are we currently pointing to the first item in the list?
  @param list the sorted list.
  @return true if pointing to the first item, false otherwise.
  */
  boolean (*isFirst)(const sortedList list);
  /** Are we currently pointing to the last item in the list?
  @param list the sorted list.
  @return true if pointing to the last item, false otherwise.
  */
  boolean (*isLast)(const sortedList list);
  /** Is there another item after current item in the list?
  @param list the sorted list.
  @return true if successful, false otherwise.
  */
  boolean (*hasNext)(const sortedList list);
  /** Is there another item before current item in the list?
  @param list the sorted list.
  @return true if successful, false otherwise.
  */
  boolean (*hasPrevious)(const sortedList list);
  /*--- item */
  /** Find this item (with certain attribute, e.g. with this key) 
  from the list and return the one from the list.
  Use <code>g_reply (*compareItem)(const void *, const void *)</code> as
  a way to compare the items.
  @param list the sorted list.
  @param anItem the item to compare against those in the list.
  @return Return the found item, 
    <code>NULL</code> if not found or failure occurs.
  */
  void *(*findItem)(const sortedList list, const void *anItem);
  /** Find this item (with certain attribute, e.g. with this key) 
  from the list and return a clone of the one from the list.
  Use <code>g_reply (*compareItem)(const void *, const void *)</code> as
  a way to compare the items.
  @param list the sorted list.
  @param anItem the item to compare against those in the list.
  @return Return a clone of the found item, 
    <code>NULL</code> if not found or failure occurs.
  */
  void *(*findItemClone)(const sortedList list, 
      const void *anItem, const void *aControlObj);
  /** Obtain the item currently pointing to in the list. 
  <p>WARNING: Do not change the item, or the list and its' sorting 
  will NOT work properly!
  This is provided for better speed. If speed is NOT a concern then recommend 
  to use <code>getItemClone(..)</code> instead, to minimise possible 
  modification to list item. If modification is required use 
  <code>modifyItem(..)</code> or <code>modifyItemClone(..)</code> function.
  </p>
  @param list the sorted list.
  @return a "cloned" copy of the item currently pointing to in the list, or
    <code>NULL</code> if failure.
  */
  void *(*getItem)(const sortedList list);
  /** Obtain a "cloned" copy of the item currently pointing to in the list. 
  <p>You SHOULD free this "cloned" copy of the item cloned from the list.
  The list does NOT keep track of these "clones" and shouldn't release them..
  <br/>UNLESS the item does some trick to <b>keep track of it's own clone</b>, 
  AND also release them via the same function pointer call to 
  <code>boolean (*freeItem)(void **)</code>.
  <br/><b>Advice:</b> Read the item's library for details.
  </p>
  @param list the sorted list.
  @param aControlObj an object that customized function may work with,
    e.g. provide cloning ability, other facility and perform other duty.
  @return a "cloned" copy of the item currently pointing to in the list, or
    <code>NULL</code> if failure.
  */
  void *(*getItemClone)(const sortedList list, const void *aControlObj);
  /** Delete the current item from the list. 
  After deletion the new current item will become the next item if it exist, 
  otherwise the new current item will become the item in front if it exist.
  If no item exist in front or to the back, the list is empty, 
  current has no item and points to <code>NULL</code>.
  @param list the sorted list.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*deleteItem)(sortedList list);
  /** Delete the current item from the list 
  BUT will NOT free the deleted item from memory!
  After deletion the new current item will become the next item if it exist, 
  otherwise the new current item will become the item in front if it exist.
  If no item exist in front or to the back, the list is empty, 
  current has no item and points to <code>NULL</code>.
  @param list the sorted list.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*deleteItemNOTFree)(sortedList list);
  /** Set a new item over the current item in the list, 
  BUT will NOT free the previous item from memory!
  Note this is NOT adding.
  @param list the sorted list.
  @param anItem the item to be added.
  @param aControlObj an object that customized function may work with,
    e.g. increasing some specific counter or doing other duty 
    when a specific action has occurred.
  @return <code>true</code> if successfully, 
    or <code>false</code> if failure occurs.
  */
  boolean (*setItemNOTFree)(sortedList list, void *anItem);
  /** Add the item into the list, according to the sorting order.
  NB: item is allow to be <code>NULL</code>.
  <p>If the item already exist, control is pass to customized function 
  <code>doEqualAction(..)</code> to handle the situation.
  If the item is new, a prepare add event customized function 
  <code>doAddPrepareAction(..)</code> will be called.
  </p>
  <p>After this item is added,
  if add is successful, specific customized function after the event 
  add item before current <code>doAddBeforeSuccessAction(..)</code>
  or add item after current <code>doAddAfterSuccessAction(..)</code> 
  will be called.
  </p>
  @param list the sorted list.
  @param anItem the item to be added.
  @param aControlObj an object that customized function may work with,
    e.g. increasing some specific counter or doing other duty 
    when a specific action has occurred.
  @return <code>true</code> if successfully, 
    or <code>false</code> if failure occurs.
  */
  boolean (*addItem)(sortedList list, 
      void *anItem, void *aControlObj);
  /** Add the item into the list, according to the sorting order.
  NB: item is allow to be <code>NULL</code>.
  <p>If the item already exist, control is pass to customized function 
  <code>doEqualCloneAction(..)</code> to handle the situation.
  If the item is new, a prepare add event customized function 
  <code>setFnDoAddPrepareCloneAction(..)</code> will be called.
  </p>
  <p>Then the item will be cloned and then added into the list.
  After this cloned item is added,
  if add is successful, specific customized function after the event 
  add item before current <code>doAddBeforeSuccessCloneAction(..)</code>
  or add item after current <code>doAddAfterSuccessCloneAction(..)</code> 
  will be called.
  </p>
  <p>You are require to free the pass in item because 
  it has not been added into the list. 
  However its' cloned copy will be free by this list via the 
  same function pointer call to <code>boolean (*freeItem)(void **)</code>,
  this is because the cloned item's been added into the list.
  </p>
  @param list the sorted list.
  @param anItem the item to be cloned and the clone will be added.
  @param aControlObj an object that customized function may work with,
    e.g. increasing some specific counter or doing other duty 
    when a specific action has occurred.
  @return <code>true</code> if successfully, 
    or <code>false</code> if failure occurs.
  */
  boolean (*addItemClone)(sortedList list, 
      const void *anItem, void *aControlObj);
  /** Modify current item with this new item.
  This function is equivalent to calling <code>deleteItem(..)</code>
  then <code>addItem(..)</code>.
  @param list the sorted list.
  @param anItem the item to be added.
  @param aControlObj an object that customized function may work with,
    e.g. provide cloning ability, other facility and perform other duty.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*modifyItem)(sortedList list, 
      void *anItem, void *aControlObj);
  /** Modify current item with a clone of this new item, 
  i.e. do not add this new item in directly but use a clone of it.
  This function is equivalent to calling <code>deleteItem(..)</code>
  then <code>addItemClone(..)</code>.
  <p>You are require to free the pass in item because 
  it has not been added into the list. 
  However its' cloned copy will be free by this list via the 
  same function pointer call to <code>boolean (*freeItem)(void **)</code>,
  this is because the cloned item's been added into the list.
  </p>
  @param list the sorted list.
  @param anItem the item to be added.
  @param aControlObj an object that customized function may work with,
    e.g. provide cloning ability, other facility and perform other duty.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*modifyItemClone)(sortedList list, 
      const void *anItem, void *aControlObj);
  /*--- provide customized function */
  /** Provide a function to clone an item of type <code>void *</code>.
  The function is of the form 
  <code>void *(*itemClone)(const void *, const void *)</code>.
  <p>This is a customized function provided by the item's library 
  and is NOT compulsory.
  </p>
  <p>WARNING: Anything that is added into the list, cloned or NOT cloned will
  be free by this list. Know what you're doing, use the right function 
  for the work, those that provide cloning ability 
  and/or NO cloning ability.
  </p>
  @param list the sorted list.
  @param itemClone the function to clone an item of type <code>void *</code>.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*setFnItemClone)(sortedList list, 
      void *(*itemClone)(const void *anItem, const void *aControlObj));
  /** Provide a "do equal action" customized function 
  for <code>addItem(..)</code>, the function will be called when 
  <code>compareItem</code> return a <code>g_replyEqual</code>, 
  i.e. item already exist within the list, customized function 
  <code>doEqualAction</code> will handle this situation.
  The function is of the form 
  <code>boolean (*doEqualAction)(sortedList, void *, void *)</code>.
  @param list the sorted list.
  @param doEqualAction the customized function.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*setFnDoEqualAction)(sortedList list, 
      boolean (*doEqualAction)(sortedList list, 
          void *anItem, void *aControlObj));
  /** Provide a "do equal clone action" customized function 
  for <code>addItemClone(..)</code>, the function will be called when 
  <code>compareItem</code> return a <code>g_replyEqual</code>, 
  i.e. item already exist within the list, customized function 
  <code>doEqualCloneAction</code> will handle this situation.
  The function is of the form 
  <code>boolean (*doEqualCloneAction)(sortedList, void *, void *)</code>.
  @param list the sorted list.
  @param doEqualCloneAction the customized function.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*setFnDoEqualCloneAction)(sortedList list, 
      boolean (*doEqualCloneAction)(sortedList list, 
          const void *anItem, void *aControlObj));
  /** Provide a "do add prepare action" customized function 
  for <code>addItem(..)</code>, the function will be called before 
  adding the item into list e.g. <code>aControlObj</code> 
  could perform specialized counting and other duties.
  The function is of the form 
  <code>boolean (*doAddPrepareAction)(void *)</code>.
  @param list the sorted list.
  @param doAddPrepareAction the customized function.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*setFnDoAddPrepareAction)(sortedList list, 
      boolean (*doAddPrepareAction)(void *aControlObj));
  /** Provide a "do add prepare action" customized function 
  for <code>addItemClone(..)</code>, the function will be called before 
  adding the cloned item into list e.g. <code>aControlObj</code> 
  could perform specialized counting and other duties.
  The function is of the form 
  <code>boolean (*doAddPrepareCloneAction)(void *)</code>.
  @param list the sorted list.
  @param doAddPrepareCloneAction the customized function.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*setFnDoAddPrepareCloneAction)(sortedList list, 
      boolean (*doAddPrepareCloneAction)(void *aControlObj));
  /** Provide a "do add before success action" customized function 
  for <code>addItem(..)</code>, the function will be called AFTER 
  the event of successfully adding an item before the current pointer 
  in the list e.g. <code>aControlObj</code> could perform 
  specialized counting and other duties.
  The function is of the form 
  <code>boolean (*doAddBeforeSuccessAction)(void *)</code>.
  @param list the sorted list.
  @param doAddBeforeSuccessAction the customized function.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*setFnDoAddBeforeSuccessAction)(sortedList list, 
      boolean (*doAddBeforeSuccessAction)(void *aControlObj));
  /** Provide a "do add before success action" customized function 
  for <code>addItemClone(..)</code>, the function will be called AFTER 
  the event of successfully adding a cloned item before the current pointer 
  in the list e.g. <code>aControlObj</code> could perform 
  specialized counting and other duties.
  The function is of the form 
  <code>boolean (*doAddBeforeSuccessCloneAction)(void *)</code>.
  @param list the sorted list.
  @param doAddBeforeSuccessCloneAction the customized function.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*setFnDoAddBeforeSuccessCloneAction)(sortedList list, 
      boolean (*doAddBeforeSuccessCloneAction)(void *aControlObj));
  /** Provide a "do add after success action" customized function 
  for <code>addItem(..)</code>, the function will be called AFTER 
  the event of successfully adding an item after the current pointer 
  in the list e.g. <code>aControlObj</code> could perform 
  specialized counting and other duties.
  The function is of the form 
  <code>boolean (*doAddAfterSuccessAction)(void *)</code>.
  @param list the sorted list.
  @param doAddAfterSuccessAction the customized function.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*setFnDoAddAfterSuccessAction)(sortedList list, 
      boolean (*doAddAfterSuccessAction)(void *aControlObj));
  /** Provide a "do add after success action" customized function 
  for <code>addItemClone(..)</code>, the function will be called AFTER 
  the event of successfully adding a cloned item after the current pointer 
  in the list e.g. <code>aControlObj</code> could perform 
  specialized counting and other duties.
  The function is of the form 
  <code>boolean (*doAddAfterSuccessCloneAction)(void *)</code>.
  @param list the sorted list.
  @param doAddAfterSuccessCloneAction the customized function.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*setFnDoAddAfterSuccessCloneAction)(sortedList list, 
      boolean (*doAddAfterSuccessCloneAction)(void *aControlObj));
};

/** Create a new sortedList.
<p>MUST provide a function to free an item of type <code>void *</code>.
The function is of the form <code>boolean (*freeItem)(void **)</code>.
</p>
<p>MUST provide a function to compare two items of type <code>void *</code>.
The function is of the form 
<code>g_reply (*compareItem)(const void *, const void *)</code>.
</p>
<p>Default <code>lesserFirst</code> is set to <code>true</code>. 
If set to <code>true</code> sorting will place 
item whose comparison value is lesser at the front. 
Otherwise set to <code>false</code> sorting will place 
item whose comparison value is greater at the front. 
</p>
@param freeItem the function to free an item of type <code>void *</code>.
@param compareItem the function to compare two items of type <code>void *</code>.
@return a newly created and empty sortedList, 
  or <code>NULL</code> if failure.
*/
sortedList ysortedList_create(boolean (*freeItem)(void **anItemP),
    g_reply (*compareItem)(const void *anItem1, const void *anItem2));

/*======= function DISABLED! */
/** FUNCTION DISABLE DUE TO UNABLE TO PROVIDE NECESSARY 
customized function (above) BEFORE ITEM IS ADDED INTO THE SORT LIST.
Create a new sortedList with this item.
<p>MUST provide a function to free an item of type <code>void *</code>.
The function is of the form <code>boolean (*freeItem)(void **)</code>.
</p>
<p>MUST provide a function to compare two items of type <code>void *</code>.
The function is of the form 
<code>g_reply (*compareItem)(const void *, const void *)</code>.
</p>
@param anItem the item to be added.
@param aControlObj an object that customized function may work with,
  e.g. provide cloning ability, other facility and perform other duty.
@param freeItem the function to free an item of type <code>void *</code>.
@param compareItem the function to compare two items of type <code>void *</code>.
@return a newly created sortedList with item, 
  or <code>NULL</code> if failure.
sortedList ysortedList_createWithItem(void *anItem, void *aControlObj,
    boolean (*freeItem)(void **anItemP),
    g_reply (*compareItem)(const void *anItem1, const void *anItem2));
*/
/** FUNCTION DISABLE DUE TO UNABLE TO PROVIDE NECESSARY 
customized function (above) BEFORE ITEM IS ADDED INTO THE SORT LIST.
Create a new sortedList with a clone of this item.
<p>MUST provide a function to free an item of type <code>void *</code>.
The function is of the form <code>boolean (*freeItem)(void **)</code>.
</p>
<p>MUST provide a function to compare two items of type <code>void *</code>.
The function is of the form 
<code>g_reply (*compareItem)(const void *, const void *)</code>.
</p>
<p>You are require to free the pass in item because 
it has not been added into the list. 
However its' cloned copy will be free by this list via the 
same function pointer call to <code>boolean (*freeItem)(void **)</code>,
this is because the cloned item's been added into the list.
</p>
@param anItem the item to be cloned and the clone will be added.
@param aControlObj an object that customized function may work with,
  e.g. provide cloning ability, other facility and perform other duty.
@param freeItem the function to free an item of type <code>void *</code>.
@param compareItem the function to compare two items of type <code>void *</code>.
@param itemClone the function to clone an item of type <code>void *</code>.
@return a newly created sortedList with item, 
  or <code>NULL</code> if failure.
sortedList ysortedList_createWithItemClone(void *anItem, void *aControlObj,
    boolean (*freeItem)(void **anItemP),
    g_reply (*compareItem)(const void *anItem1, const void *anItem2),
    void *(*itemClone)(const void *anItem, const void *aControlObj));
*/

#endif /* _YSORTEDLIST_H */
